package src{

import flash.display.*;
import flash.events.*;
import src.*;

public class BoardCol extends Object{
	var emptyBoard:Array;	//1 dim
	var allBoard1d:Array;
	var allBoard:Array;		//2 dim [i][j]
	public var oriOwner:Array;		//for AI testing purpos
	//array of owner, associated with boardCol.getAll1d
	
	public function BoardCol(copyBc:BoardCol = null){
		emptyBoard = new Array();
		allBoard = new Array();
		allBoard1d = new Array();
		if(copyBc != null){
			//copy constructor
			var bo:Board;
			for(var i=0;i<copyBc.allBoard.length;i++){
				for(var j=0;j<copyBc.allBoard[i].length;j++){
					bo = copyBc.allBoard[i][j];
					var newBo:Board = new Board(i,j);
					newBo.setOwner(bo.getOwner);
					add(newBo,i,j);
				}
			}
			for(i=0;i<emptyBoard.length;i++){
				//remove all owned boards
				bo = emptyBoard[i];
				if(bo.getOwner != ""){
					emptyBoard.splice(i,1);
					i--;
				}
			}
		}
	}
	public function add(bo:Board, i:Number,j:Number){
		if(allBoard[i] == null) allBoard[i] = new Array();
		allBoard[i][j] = bo;
		allBoard1d.push(bo);
		emptyBoard.push(bo);
	}
	public function remove(bo:Board){
		Mi.removeFromArr(bo,emptyBoard);
	}
	public function find(bo:Board){
		//finds board in this collection that is the same i and j with the bo
		return allBoard[bo.iPos][bo.jPos];
	}
	public function checkWinner():String{ //check who wins
		//return the "","pl" or "en"
		var pl:Number; //count of boards owned by pl
		var en:Number; //by en
		var winner:String = "";
		var boardDim:Number = getAll.length;
		function counter(bo:Board):void{
			var own:String = bo.getOwner;
			if(own == "pl") pl++;
			else if(own == "en") en++;
		}
		function check():Boolean{
			//return true if someone wins
			if(pl == boardDim) winner = "pl";
			else if(en == boardDim) winner = "en";
			return winner != "";
		}
		function init():void{
			pl=0; en=0;
		}
		//vertical lines
		for(var i=0;i<boardDim;i++){
			init();
			for(var j=0;j<boardDim;j++){
				counter(getAll[i][j]);
			}
			if(check()) break;
		}
		//horizontal lines
		for(j=0;j<boardDim;j++){
			init();
			for(i=0;i<boardDim;i++){
				counter(getAll[i][j]);
			}
			if(check()) break;
		}
		//diagonal (only 2 diagonal)
		init();
		for(i=0;i<boardDim;i++){
			counter(getAll[i][i]);
		}
		check();
		init();
		for(i=0;i<boardDim;i++){
			counter(getAll[i][boardDim-i-1]);
		}
		check();
		return winner;
	}
	
	public function setOwner(bo:Board, id:String):void{
		bo.setOwner(id);
		remove(bo);
	}
	public function get getEmpty():Array{
		return emptyBoard;
	}
	public function get getAllPossibleMove():Number{
		var cou:Number = 1;
		for(var i=1;i<=getEmpty.length;i++){
			cou *= i;
		}
		return cou;
	}
	
	public function cannotCreateFullPath(currentBo:Board):Boolean{
		var dim:Number = getAll.length;
		var iPos:Number = currentBo.iPos;
		var jPos:Number = currentBo.jPos;
		
		var cannotCount:Number = 0;
		for(var i=0;i<dim;i++){
			var bo:Board = getAll[i][jPos];
			if(bo.getOwner == "pl"){
				cannotCount++;
				break;
			}
		}
		for(var j=0;j<dim;j++){
			bo = getAll[iPos][j];
			if(bo.getOwner == "pl"){
				cannotCount++;
				break;
			}
		}
		//check if diagonal possible
		var canDiagonal:Boolean;
		var cannotMax:Number;
		if(iPos == jPos || (iPos+jPos==dim-1)){
			canDiagonal = true;
			cannotMax = 4;
		}else{
			canDiagonal = false;
			cannotMax = 2;
		}
		if(canDiagonal){
			for(i=0;i<dim;i++){
				bo = getAll[i][i];
				if(bo.getOwner == "pl"){
					cannotCount++;
					break;
				}
			}
			for(i=0;i<dim;i++){
				bo = getAll[dim-i-1][i];
				if(bo.getOwner == "pl"){
					cannotCount++;
					break;
				}
			}
		}
		return (cannotCount >= cannotMax);
	}
	public function getEmptyGood(curTurn:String):Array{
		//get the most adjacent to each other, placed in the top (near 0) of the array index, to fasten the AI
		var resArr:Array = new Array();
		var resObjArr:Array = new Array();
		for(var i=0;i<emptyBoard.length;i++){
			var bo:Board = emptyBoard[i];
			var adjCount:Number = findAdjacent(bo,curTurn);
			//1 if there is adjacent, 0 no
			resObjArr.push({bo:bo, adj:adjCount});
		}
		resObjArr.sortOn("adj",Array.NUMERIC | Array.DESCENDING);
		for(i=0;i<resObjArr.length;i++){
			resArr.push(resObjArr[i].bo);
		}
		return resArr;
	}
	public function findAdjacent(bo:Board,curTurn:String):Number{
		var i:Number = bo.iPos;
		var j:Number = bo.jPos;
		var dim:Number = getAll.length;
		var cou:Number = 0;
		function count(it:Number,jt:Number):void{ //i/j target
			if(it<0 || jt<0 || it>=dim || jt>=dim) return;
			if(getAll[it][jt].getOwner == curTurn){
				cou++;
			}
		}
		count(i-1,j-1); count(i-1,j); count(i-1,j+1);
		count(i,j-1); count(i,j); count(i,j+1);
		count(i+1,j-1); count(i+1,j); count(i+1,j+1);
		return cou;
	}
	
	public function retrieveEmptyGood(emptyArr:Array):Array{
		//retrieve from another boardCol, to fasten
		var resArr:Array = new Array();
		for(var i=0;i<emptyArr.length;i++){
			var bo:Board = emptyArr[i];
			resArr.push(getAll[bo.iPos][bo.jPos]);
		}
		return resArr;
	}
	public function get getRandEmpty():Board{
		return getEmpty[Mi.intRandom(0,getEmpty.length-1)];
	}
	public function get getAll():Array{
		return allBoard;
	}
	public function get getAll1d():Array{
		//1 dimensional array
		return allBoard1d;
	}
}

}